Skip to content

feat : B1 캘린더용 정책상품 회차·온통청년 청년정책 수집 - #19

Draft
yuyeol3 wants to merge 6 commits into
mainfrom
yuyeol3/feat/youth-policy-calendar
Draft

yuyeol3 wants to merge 6 commits into
mainfrom
yuyeol3/feat/youth-policy-calendar

Conversation

@yuyeol3

@yuyeol3 yuyeol3 commented Nov 1, 2026 •

Copy link
Copy Markdown
Collaborator

변경점 👍

B1 캘린더 데이터를 수집합니다. 스키마(V10)와 조회 API는 ApptiveDev/Fin-BE#43에 있습니다.

계층 원천 저장
1계층: 정책상품 회차 manual-product-rounds.json(사람이 관리) policy_product_round
2계층: 온통청년 정책 온통청년 getPlcy API youth_policy, youth_policy_round

1. 1계층: 정책상품 회차 (policyround)

  • 온통청년과 자동으로 연결하지 않고 파일로 관리합니다.
    • 온통청년은 정책번호가 해마다 바뀌고, 공고보다 늦게 올리거나 아예 올리지 않습니다(2026년 16종 중 시작 전 등록 4종).
    • PRD "운영자가 승인한 회차만 노출"과 같습니다.
  • 2026 데이터: 14종 17회차, 회차마다 근거 링크
    • 경기 청년 노동자 통장(2026 모집 미정), 대구 청년희망적금(2026 공고 없음)은 rounds 비우고 note에 사유
  • 동기화(PolicyProductRoundSyncService)
    • 상품은 source=ONTONG + product_code로 찾음
    • 파일 안 순서(round_no)로 맞추고, 날짜가 바뀌면 schedule_changed_at 기록, 파일에서 빠진 회차는 삭제
    • 아직 수집 안 된 상품은 건너뛰고 경고 로그
    • 파일 형식 오류(시작일 누락, 순서 역전)는 step 실패
  • manual-products.json: POLICY014 이름을 세종청년희망적금으로 변경(2026 사업명)

2. 2계층: 온통청년 정책 (youthpolicy)

  • 범위: PRD 개요의 "자산형성 저축·공제·신용회복"(2026-11 기준 3,843건 중 90건)
    • 정책 이름 키워드로 고르고 온통청년 분류는 보지 않습니다. 분류로 거르면 내일채움공제(재직자), 학자금 신용회복(교육비지원)이 빠집니다.
    • 주거(청약통장, 전세·임차 대출이자 등)와 세금 공제는 제외
    • 상수: YouthPolicyParser.SCOPE_NAME, EXCLUDED_NAME
  • 파싱: 신청기간 구분(PERIOD/ALWAYS/CLOSED), 여러 회차(\N 구분), 나이 0 → NULL, 읽을 수 없는 회차는 경고 후 버림
  • 동기화: 정책 번호로 upsert, 날짜 바뀐 회차만 변경 기록, 사라진 정책은 비활성화

3. 배치

  • Source.CALENDAR → calendarSyncFlow: syncPolicyProductRoundStep → syncYouthPolicyStep
    • 상품 수집과 따로 돌릴 수 있게 분리(PRD: 하루 1회 이상 갱신)
  • ALL에도 마지막 step들로 포함(정부상품 정규화 뒤라야 회차를 붙일 상품이 있음)
  • 범위 안 정책이 0건이면 syncYouthPolicyStep 실패(전체 비활성화 방지)

버그 해결 💊

  • OntongYouthClient: 온통청년이 가끔 HTML 오류 페이지나 400·403·500을 돌려줌 → 페이지마다 3번까지 재시도
    • 실제로 여러 번 받아 보니 39페이지 중 0~2번씩 발생, 모두 재시도로 회복
    • 로그와 예외에는 예외 종류만 남김(I/O 오류 메시지에 API 키가 든 URL이 들어감)

테스트 💻

  • ./gradlew test 404개 통과
  • 추가·변경한 테스트
    • YouthPolicyParserTest 11: 회차 분리, 상시·마감, 읽을 수 없는 날짜, 나이 0, 범위 키워드, 오탐 이름, 주거 제외, 분류 무관 선택
    • PolicyProductRoundSyncServiceTest 4(Testcontainers): 저장, 날짜 변경 표시, 빠진 회차·상품 삭제, 미수집 상품 건너뜀
    • YouthPolicySyncServiceTest 4(Testcontainers): 저장, 변경 표시, 삭제·비활성화, 재활성화
    • ManualProductRoundsFileTest: 회차 파일 형식과 상품 코드가 manual-products.json과 일치
    • SyncYouthPolicyTaskletTest 3, OntongYouthClientTest 3, AllSyncFlowTest(새 step 반영)
  • 변이 검사: 날짜 변경 감지, 빠진 상품 회차 삭제를 빼면 동기화 테스트 실패 확인
  • 실제 API: 빈 Postgres(Fin-BE#43 V10) → ONTONG → CALENDAR 순서로 실행(LLM 끔)
    • 1회차: 정책상품 회차 17개, 온통청년 90건 저장(저축 55, 공제 18, 신용회복 17)
    • 2회차: 회차 변경 0건, 비활성화 0건

비고 ✏

  • 서브모듈: fin-be가 머지 전 Fin-BE 캘린더 브랜치 커밋(a877ba8)을 가리킵니다. 그래서 draft입니다.
  • 머지 순서: Fin-BE#41(V9) → Fin-BE#43(V10) → 서브모듈 포인터를 main 커밋으로 갱신 → 이 PR
  • 소스 이름 변경: 처음 올린 YOUTH_POLICY를 CALENDAR로 바꿨습니다. 아직 이 이름을 쓰는 워크플로는 없습니다.
  • 운영 반영: 머지 후 다음 ALL 수집부터 캘린더 데이터가 채워집니다. 매일 실행 워크플로(COLLECTOR_SOURCE=CALENDAR)는 chore : 2주 간격 수집 워크플로 추가 (main→dev, release→운영 DB) #18 머지 후 따로 올릴 예정입니다.
  • 1계층 갱신 방법: 새 공고가 나오면 manual-product-rounds.json에 회차를 추가하는 PR을 올리면 됩니다. 온통청년 새 회차 후보 알림은 아직 없습니다.

궁금한 점 있으시면 편하게 질문 주세요!

@yuyeol3 yuyeol3 changed the title feat : B1 캘린더용 온통청년 청년정책 수집 feat : B1 캘린더용 정책상품 회차·온통청년 청년정책 수집 Nov 1, 2026

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant